{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Aria2.Method where

import Aria2.GID (GID)
import Aria2.Options (Options)
import Aria2.Status (StatusKey)
import Data.Int (Int64)
import Data.Text (Text)
import Data.Vector.NonEmpty (NonEmptyVector)
import Data.Word (Word64)
import Text.URI (URI)

newtype Base64 = Base64 Text
  deriving stock (Show)
  deriving newtype (Eq)

data PositionChangeOrigin = FromCurrent | FromFront | FromBack
  deriving stock (Eq, Show)

data QueuePosition = Back | Place {-# UNPACK #-} !Word
  deriving stock (Eq, Show)

data QueueRange = QueueRange {-# UNPACK #-} !Int64 {-# UNPACK #-} !Word64
  deriving stock (Eq, Show)

-- methods not implemented:

-- * changeUri (too hard)

-- * changeOption (too hard)

-- * changeGlobalOption (even harder)

data MethodDetail
  = -- | Based on https://aria2.github.io/manual/en/html/aria2c.html#aria2.addUri
    -- This deals with only non-magnet requests, for added type safety.
    AddUri
      {-# UNPACK #-} !(NonEmptyVector URI)
      !Options
      !(Maybe QueuePosition)
  | AddMagnetUri
      {-# UNPACK #-} !URI
      !Options
      !(Maybe QueuePosition)
  | AddTorrent
      {-# UNPACK #-} !Base64
      !(Maybe (NonEmptyVector URI))
      !Options
      !(Maybe QueuePosition)
  | AddMetalink
      {-# UNPACK #-} !Base64
      !(Maybe (NonEmptyVector URI))
      !Options
      !(Maybe QueuePosition)
  | Remove {-# UNPACK #-} !GID
  | ForceRemove {-# UNPACK #-} !GID
  | Pause {-# UNPACK #-} !GID
  | PauseAll
  | ForcePause {-# UNPACK #-} !GID
  | ForcePauseAll
  | Unpause {-# UNPACK #-} !GID
  | UnpauseAll
  | TellStatus
      {-# UNPACK #-} !GID
      {-# UNPACK #-} !(NonEmptyVector StatusKey)
  | GetUris {-# UNPACK #-} !GID
  | GetFiles {-# UNPACK #-} !GID
  | GetPeers {-# UNPACK #-} !GID
  | GetServers {-# UNPACK #-} !GID
  | TellActive {-# UNPACK #-} !(NonEmptyVector StatusKey)
  | TellWaiting
      {-# UNPACK #-} !QueueRange
      {-# UNPACK #-} !(NonEmptyVector StatusKey)
  | TellStopped
      {-# UNPACK #-} !QueueRange
      {-# UNPACK #-} !(NonEmptyVector StatusKey)
  | ChangePosition
      {-# UNPACK #-} !GID
      !PositionChangeOrigin
      {-# UNPACK #-} !Int64
  | GetOption {-# UNPACK #-} !GID
  | GetGlobalOption
  | GetGlobalStat
  | PurgeDownloadResult {-# UNPACK #-} !GID
  | RemoveDownloadResult {-# UNPACK #-} !GID
  | GetVersion
  | GetSessionInfo
  | Shutdown
  | ForceShutdown
  | SaveSession
  deriving stock (Show, Eq)

data Method = Method {-# UNPACK #-} !Text !MethodDetail
  deriving stock (Show, Eq)
